/***************************************************************************
 *   Copyright (C) 2007 by Andreas Theofilu                                *
 *   andreas@TheoSys.at                                                    *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation version 3 of the License.                *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

// TILGRECH.CPP
// Modul zur Berechnung eines Tilgungsplans.
// Die errechneten Daten werden in einer Datei zwischengespeichert und
// können so auf jede beliebige Art verwendet werden.
#include <klocale.h>
#include <kmessagebox.h>
#include <qfile.h>
#include <qstring.h>
#include <qdir.h>
#include <qdatetime.h>

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <sys/stat.h>

#include "tilgplan.h"
#include "helper.h"

int MonLeiste[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
		 /*  Jan Feb Mär Apr Mai Jun Jul Aug Sep Okt Nov Dez */;

// Wenn dieses Modul mit dem Flag "_ZINSAENDERUNG" compiliert wurde, kann
// eine Zinssatzänderung definiert werden. Dazu ist ein eigenes Dialog-
// fenster notwendig.

// Funktionen -------------------------------------------------------------

// Hauptprogramm
// Durch aufrufen dieser Routine wird ein Tilgungsplan auf Grund der
// übergebenen Parameter errechnet und in einer Datei abgelegt.
// Diese kann dann weiter bearbeitet werden.
//
// Die übergebenen Parameter enthalten auch Steuerkennzeichen. So kann auch
// der Effektivzinssatz berechnet werden. Dazu muss der Kredit zunächst
// normal durchgerechnet werden. Anschliessen wird mit der errechneten Rate,
// jedoch ohne Spesen, Gebühren etc. der Plan für ein Jahr noch einmal
// gerechnet. Die so ermittelten Zinsen ergeben den Effektivzinssatz.
//

int TRech::tilgpl ()
{
int day, mon, year, akt_mon, akt_year, i, j;

	// initialisieren
	init_global_vars ();

	if (TpPars->dvon == 0L)
	   return 2;			// 1. Einschränkung nicht vorhanden

        // Datum der ersten Einschränkung korrigieren falls notwendig
	date_int (&day, &mon, &year, TpPars->dvon);

	if (TpPars->ultimo)		// Wenn Ultimo Datum korrigieren
	{
	   set_feb (year);
	   day = MonLeiste[mon-1];
	   TpPars->dvon = make_date (day, mon, year);
	}

	// Auszahlungsdatum überprüfen

	if (TpPars->ragab == 0L)
	   return 8;			// Auszahlungsdatum nicht vorhanden

	// Auszahlungsdatum auf Gültigkeit überprüfen

	if (TpPars->ragab > TpPars->dvon)
	   return 3;			// Auszahlungsdatum > 1. Einschränkung

	if (TpPars->effekt && TpPars->rate <= 0.0)
	   return 29;			// Keine Rate, kein Effektivzins!

	// Abschlußrhythmus überprüfen

	if (TpPars->effekt && TpPars->abschlry != 12 && TpPars->abschlry != 52)
	   return 26;			// Für Effektivzinssatzberechnung nur jährlicher Abschluss erlaubt

	if (TpPars->abschlry != 1 && TpPars->abschlry != 3 && TpPars->abschlry != 6 &&
	    TpPars->abschlry != 12 && TpPars->abschlry != 41 && TpPars->abschlry != 43 &&
	    TpPars->abschlry != 46 && TpPars->abschlry != 47 && TpPars->abschlry != 48 &&
	    TpPars->abschlry != 52)
	   return 11;			// ungültiger Abschlußrythmus

	if (TpPars->abschlry > 40)	// Abschlüsse auf Ultimo rechnen?
	   TpPars->abschl = 0L;		// Ja, Abschlußdatum initialisieren

	// Abschlußdatum überprüfen

	if (TpPars->abschl > 0L && TpPars->abschl < TpPars->ragab)
	   return 4;			// Abschlußdatum < Auszahlungsdatum

	if (TpPars->abschl == 0L && TpPars->abschlry < 41)
	   return 10;			// Abschlußdatum muß angegeben werden

	// Abschlußplan erstellen;

	for (i = 0; i < 12; i++)
	   AbschlPlan[i] = 0;

	switch (TpPars->abschlry)
	{
	   case  1:
           case 41: for (i = 0; i < 12; i++)
		       AbschlPlan[i] = 1;
	   break;

	   case  3:
           case 43: AbschlPlan[2] = 1;
		    AbschlPlan[5] = 1;
		    AbschlPlan[8] = 1;
		    AbschlPlan[11] = 1;
	   break;

	   case  6:
           case 46: AbschlPlan[5] = 1;
		    AbschlPlan[11] = 1;
	   break;

	   case 12:
	   case 52: AbschlPlan[11] = 1;
	   break;

	   case 47: AbschlPlan[2] = 1;
		    AbschlPlan[8] = 1;
	   break;

	   case 48: AbschlPlan[1] = 1;
		    AbschlPlan[7] = 1;
	   break;
	}

	// Ratenvorgabe?

	if (TpPars->fixrate)
	{
	   if (TpPars->rate < 0.0)
	      return 16;		// Ratenvorgabe negativ
	   else if (TpPars->rate == 0.0)
	      return 15;		// keine Ratenvorgabe

	   // Datum der letzten Einschränkung initialisieren
	   TpPars->dbis = 0.0;
        }
	else				// Rate initialisieren
	   TpPars->rate = 0.0;

	// Datum der letzten Einschränkung überprüfen

	if (!TpPars->fixrate)		// Nur wenn keine Ratenvorgabe
	{
	   date_int (&i, &akt_mon, &akt_year, TpPars->dvon);
	   date_int (&day, &akt_mon, &akt_year, TpPars->dbis);
	   set_feb (akt_year);

	   // Da das Datum der letzten Einschränkung nur aus Monat und
	   // Jahr besteht, muß noch der Tag hinzugefügt werden, um
	   // damit rechnen zu können.

	   if (i > MonLeiste[akt_mon-1])
	      i = MonLeiste[akt_mon-1];

	   TpPars->dbis = make_date (i, akt_mon, akt_year);

	   // Datum mit 1.Einschränkung gegenprüfen

	   if (TpPars->dvon > TpPars->dbis)
              return 5;			// 1. Einschränkung > letzte Einschränkung

	   // letzte Einschränkung mit Ratenleiste gegenprüfen

	   if (TpPars->raplan[akt_mon-1] <= 0)
              return 19;		// letzte Einschränkung oder Ratenleiste ungültig
	}

	// Endfälligkeitsdatum überprüfen (falls vorhanden)

	if (TpPars->endfaell > 0L && TpPars->dbis > TpPars->endfaell)
	   return 6;			// letzte Einschränkung > Endfälligkeit

	// Ratenleiste berprüfen

	i = j = 0;

	while (i < 12)
	{
	   if (TpPars->raplan[i] > 0)
	   {
	      j = 1;
	      break;
	   }

	   i++;
	}

	if (!j)
	   return 7;			// Es wurde keine Rate definiert

	// 1. Einschränkung mit Ratenleiste gegenprüfen

	date_int (&day, &mon, &year, TpPars->dvon);

	if (TpPars->raplan[mon-1] <= 0)
	   return 18;			// 1. Einschränkung oder Ratenleiste ungültig

	// Verzinsungsart überprüfen

	if (TpPars->verzart == 0 || TpPars->verzart == 2 || TpPars->verzart == 8)
	   verzinsung = 0;		// Permanent dekursiv
	else if (TpPars->verzart == 3)
	   verzinsung = 1;		// Antizipativ
	else if (TpPars->verzart == 7)
	   verzinsung = 2;		// Dekursiv
	else if (TpPars->verzart == 4)
	   verzinsung = 3;		// Quasiantizipativ
	else
	   return 12;			// ungültige Verzinsungsart

	if (TpPars->effekt && (verzinsung == 1 || verzinsung == 3))
	   return 28;			// Effektivzinss. nur bei dekursiv möglich

	// Verzinsungsart mit Abschlußrhythmus gegenprüfen

	if (TpPars->verzart == 1 && TpPars->abschlry != 43 &&
		TpPars->abschlry != 46 && TpPars->abschlry != 52)
	   return 9;			// Verzinsung in Bezug auf Abschlußrhythmus ungültig

#ifdef _ZINSAENDERUNG
	// Zinssatzänderung mit Verzinsungsart gegenprüfen

	if (TpPars->ziaend && (verzinsung == 1 || verzinsung == 3))
	   return 23;			// Zinssatzänderung unter Antizipativ nicht möglich
#endif
	// Ratenart überprüfen

	if (TpPars->ratenart < 0 || TpPars->ratenart > 3)
	   return 13;			// ungültige Ratenart

	if (TpPars->ratenart == 0)
	   reh = 1;			// Kapitalraten
	else if (TpPars->ratenart == 1)
	   reh = 2;			// Pauschalraten
	else
	   reh = 0;			// Pauschalraten

	// Divisor setzen

	if (TpPars->tageb == 1 || TpPars->tageb == 2 || TpPars->tageb == 7 ||
	    TpPars->tageb == 8)
	   divisor = 36000.0;
	else
	   divisor = 36500.0;

	// Erstellen einer Datumstabelle

	if (verzinsung == 0 || verzinsung == 2)	// Dekursiv?
	{
	   if ((i = DekursivTable ()) != 0)
	      return i;
	}
	else					// Antizipativ
	{
	   if ((i = AntizipativTable ()) != 0)
	      return i;
	}

	// Berechnung der Rate

	a_ind = r_ind = 0;

	if (TpPars->fixrate == TRUE)	// Besteht eine Ratenvorgabe?
	{
	   TpPars->ergrate = rat = TpPars->rate;
	   return Ratenplan ();
	}

	// Erstellen eines Ratenplans

        GetRate (TpPars->rahmen, TpPars->ragab, TpPars->dvon);

	TpPars->ergrate = rat;
	return Ratenplan ();
}

#ifdef _ZINSAENDERUNG

int TRech::GetZiaend ()
{
QString hdir = QDir::homeDirPath ();
QFile tmpFile;
int fd;
struct stat sbuf;
ZIAEND Zi;

	// Plausibilitätsprüfung der eingebenen Daten
	hdir.append("/.zinsaend.dat");
	tmpFile.setName(hdir);

	if (tmpFile.open(IO_ReadWrite) == FALSE)
	{
	   KMessageBox::error(0, QString("Could not open file for reading: %1").arg(tmpFile.errorString()));
	   return 23;
	}
	
	fd = tmpFile.handle();
	fstat (fd, &sbuf);

	if (sbuf.st_size == 0L)
	{
	   tmpFile.close ();
	   return 0;
	}

	while (read (fd, &Zi, sizeof(ZIAEND)) == sizeof(ZIAEND))
	{
	   if (Zi.Datum <= TpPars->dvon)
	   {
	      tmpFile.close ();
	      return 24;
	   }

	   if (Zi.Datum >= TpPars->dbis)
	   {
	      tmpFile.close ();
	      return 25;
	   }
	}

	tmpFile.close ();
	return 0;
}

#endif

int TRech::DekursivTable ()
{
long tage;
int vday, day, mon, year, akt_day, akt_mon, iday, imon, iyear;
int at, am, aj;
BOOL abschluss, r_yet;
long lab;
QDate dat1, dat2;

	// Wurde eine fixe Rate vorgegeben und ein Enfälligkeitsdatum
	// angegeben, muß die letzte Einschränkung gleich dem
	// Endfälligkeitsdatum sein.

	if (TpPars->fixrate && TpPars->endfaell > 0L)
	   TpPars->dbis = TpPars->endfaell;

	// Wurde eine fixe Rate vorgegeben und keine letzte Einschränkung
	// und keine Endfälligkeit, werden 100 Jahre im voraus gesetzt.
	// Das ist die maximale Laufzeit.

	if (TpPars->dbis == 0L)
	{
	   QDate dt;
	   date_int(&day, &mon, &year, TpPars->ragab);
	   dt.setYMD(year, mon, day);
	   dt = dt.addYears(99);
	   TpPars->dbis = dt.year() * 10000L + dt.month() * 100L + dt.day();
	}

	// Wenn auf Ultimo gerechnet wird, muß der Tag der letzten
	// Einschränkung auf den letzten des Monats gesetzt werden.
	// Einzige Ausnahme: Verzinsungsart 7. Hier muß der Tag auf den
	// 1. eines Monats gesetzt werden.

	if (TpPars->ultimo)
	{
	   date_int (&day, &mon, &year, TpPars->dbis);

	   if (TpPars->verzart == 7)
	      day = 1;
	   else
	      day = MonLeiste[mon-1];

	   TpPars->dbis = make_date (day, mon, year);
	}

	// überprüfen der Laufzeit auf Grund der eingegebenen Daten

	if (TpPars->endfaell > 0L)
	{
	   QDate dt1, dt2;
	   date_int(&day, &mon, &year, TpPars->endfaell);
	   dt1.setYMD(year, mon, day);
	   date_int(&day, &mon, &year, TpPars->ragab);
	   dt2.setYMD(year, mon, day);
	   tage = dt2.daysTo(dt1);
//	   tage = DateToDay (TpPars->endfaell) - DateToDay (TpPars->ragab);
	}
	else
	{
	   QDate dt1, dt2;
	   date_int(&day, &mon, &year, TpPars->dbis);
	   dt1.setYMD(year, mon, day);
	   date_int(&day, &mon, &year, TpPars->ragab);
	   dt2.setYMD(year, mon, day);
	   tage = dt2.daysTo(dt1);
//	   tage = DateToDay (TpPars->dbis) - DateToDay (TpPars->ragab);
	}

	if (tage > 36524L)
	   return 14;			// Laufzeit über 100 Jahre

	if (TpPars->abschl == 0L)
	   TpPars->abschl = TpPars->ragab;

	date_int (&vday, &mon, &year, TpPars->dvon);
	date_int (&day, &mon, &year, TpPars->ragab);
	date_int (&at, &am, &aj, TpPars->abschl);
	akt_mon = mon - 1;
	a_ind = r_ind = 0;
	pos = 0;
	abschluss = FALSE;
	r_yet = FALSE;			// Nur TRUE wenn "a_dat" < TpPars->dvon
	lab = 0L;

	while (pos < tage && a_ind < 1200 && r_ind < 1200)
	{
	   set_feb (year);

	   // Abschlußdatum

	   if (TpPars->abschlry > 40)
	      akt_day = MonLeiste[akt_mon];
	   else
	   {
	      if (at > MonLeiste[akt_mon])
		 akt_day = MonLeiste[akt_mon];
	      else
		 akt_day = at;
	   }

	   a_dat = make_date (akt_day, akt_mon + 1, year);

	   if (test_abschl (akt_mon+1) && AbschlPlan[akt_mon] && a_dat > TpPars->ragab)
	   {
	      ab_dat[a_ind] = a_dat;
	      lab = a_dat;

	      if (a_dat < TpPars->dvon)
		 r_yet = TRUE;

	      if (!abschluss)
	      {
		 TpPars->abschl = TpPars->ragab;
		 abschluss = TRUE;
	      }

	      a_ind++;
	   }

	   // Einschränkungsdatum

	   if (TpPars->ultimo)
	      akt_day = MonLeiste[akt_mon];
	   else
           {
	      if (vday > MonLeiste[akt_mon])
		 akt_day = MonLeiste[akt_mon];
	      else
		 akt_day = vday;
	   }

	   r_dat = make_date (akt_day, akt_mon+1, year);

	   if ((TpPars->raplan[akt_mon] && r_dat >= TpPars->dvon &&
	       r_dat <= TpPars->dbis) || r_yet)
	   {
	      rat_dat[r_ind] = r_dat;
	      ldat = r_dat;
	      rat_anz[r_ind] = TpPars->raplan[akt_mon];
	      r_ind++;
	      r_yet = FALSE;
	   }

	   akt_mon++;

	   if (akt_mon >= 12)		// Jahreswechsel
	   {
	      akt_mon = 0;
	      year++;
	   }

	   date_int(&iday, &imon, &iyear, r_dat);
	   dat1.setYMD(iyear, imon, iday);
	   date_int(&iday, &imon, &iyear, TpPars->ragab);
	   dat2.setYMD(iyear, imon, iday);
	   pos = dat2.daysTo(dat1);
//	   pos = DateToDay (r_dat) - DateToDay (TpPars->ragab), r_dat, TpPars->ragab);
	}

	if (TpPars->effekt && (r_ind >= 1200 || a_ind >= 1200))
	   return 20;			// Rechenfehler

	if (lab != a_dat)
	{
	   ab_dat[a_ind] = TpPars->dbis;
	   a_ind++;
	}

	TpPars->dbis = ldat;
	max_abs = a_ind;
        max_rat = r_ind;
	return 0;
}

int TRech::AntizipativTable ()
{
long tage;
int vday, day, mon, year, akt_day, akt_mon;
int at, am, aj;
BOOL abschluss, r_yet;
long lab;

	// Wurde eine fixe Rate vorgegeben und ein Enfälligkeitsdatum
	// angegeben, muß die letzte Einschränkung gleich dem
	// Endfälligkeitsdatum sein.

	if (TpPars->fixrate && TpPars->endfaell > 0L)
	   TpPars->dbis = TpPars->endfaell;

	// Wurde eine fixe Rate vorgegeben und keine letzte Einschränkung
	// und keine Endfälligkeit, werden 100 Jahre im voraus gesetzt.
	// Das ist die maximale Laufzeit.

	if (TpPars->dbis == 0L)
	{
	   QDate dt;
	   date_int(&day, &mon, &year, TpPars->ragab);
	   dt.setYMD(year, mon, day);
	   dt = dt.addYears(99);		// 99 Jahre ist maximale Laufzeit
	   TpPars->dbis = dt.year() * 10000L + dt.month() * 100L + dt.day();
	}

	// Wenn auf Ultimo gerechnet wird, muß der Tag der letzten
	// Einschränkung auf den letzten des Monats gesetzt werden.
	// Einzige Ausnahme: Verzinsungsart 7. Hier muß der Tag auf den
	// 1. eines Monats gesetzt werden.

	if (TpPars->ultimo)
	{
	   if (TpPars->verzart == 3)
	      day = 1;
	   else
	   {
	      date_int (&day, &mon, &year, TpPars->dbis);
	      day = MonLeiste[mon-1];
	   }

	   TpPars->dbis = make_date (day, mon, year);
	}
	else
	{
	   date_int (&day, &mon, &year, TpPars->dbis);
	   day = 1;
	   TpPars->dbis = make_date (day, mon, year);
	}
	 
	// überprüfen der Laufzeit auf Grund der eingegebenen Daten

	if (TpPars->endfaell > 0L)
	   tage = DateToDay (TpPars->endfaell) - DateToDay (TpPars->ragab);
	else
	   tage = DateToDay (TpPars->dbis) - DateToDay (TpPars->ragab);

	if (tage > 36525L)
	   return 14;			// Laufzeit �ber 100 Jahre

	if (TpPars->abschl == 0L)
	   TpPars->abschl = TpPars->ragab;

	date_int (&vday, &mon, &year, TpPars->dvon);
	date_int (&day, &mon, &year, TpPars->ragab);
	date_int (&at, &am, &aj, TpPars->abschl);
	akt_mon = mon - 1;
	a_ind = r_ind = 0;
	pos = 0;
	abschluss = FALSE;
	r_yet = FALSE;			// Nur TRUE wenn "a_dat" < TpPars->dvon
	lab = 0L;

	while (pos < tage)
	{
	   set_feb (year);

	   // Abschlußdatum

	   if (TpPars->abschlry > 40)
	      akt_day = MonLeiste[akt_mon];
	   else
	   {
	      if (at > MonLeiste[akt_mon])
		 akt_day = MonLeiste[akt_mon];
	      else
		 akt_day = at;
	   }

	   a_dat = make_date (akt_day, akt_mon + 1, year);

	   if (!abschluss)
	   {
	      ab_dat[a_ind] = TpPars->ragab;
	      lab = TpPars->ragab;
	      TpPars->abschl = TpPars->ragab;
	      abschluss = TRUE;
	      a_ind++;
           }
	   else if (test_abschl (akt_mon+1) && a_dat < TpPars->dbis)
	   {
	      a_dat = DateToDay (a_dat);
	      a_dat = DayToDate (a_dat + 1L);
	      ab_dat[a_ind] = a_dat;
	      lab = a_dat;
	      a_ind++;
           }

	   // Einschränkungsdatum

	   if (TpPars->ultimo)
	      akt_day = MonLeiste[akt_mon];
	   else
           {
	      if (vday > MonLeiste[akt_mon])
		 akt_day = MonLeiste[akt_mon];
	      else
		 akt_day = vday;
	   }

	   r_dat = make_date (akt_day, akt_mon+1, year);

	   if ((TpPars->raplan[akt_mon] && r_dat >= TpPars->dvon &&
	       r_dat <= TpPars->dbis) || r_yet)
	   {
	      rat_dat[r_ind] = r_dat;
	      ldat = r_dat;
	      rat_anz[r_ind] = TpPars->raplan[akt_mon];
	      r_ind++;
	      r_yet = FALSE;
	   }

	   akt_mon++;

	   if (akt_mon >= 12)		// Jahreswechsel
	   {
	      akt_mon = 0;
	      year++;
	   }

	   pos = DateToDay (r_dat) - DateToDay (TpPars->ragab);
	}

	if (lab != a_dat)
	{
	   ab_dat[a_ind] = TpPars->dbis;
	   a_ind++;
	}

	TpPars->dbis = ldat;
	max_abs = a_ind;
        max_rat = r_ind;
	return 0;
}

double TRech::runden (double zahl, int komma)
{
double vork, nachk;
long nk, nk1, splitter;

	if (zahl == 0.0)
	   return 0.0;

	nk = 0L;
	modf (zahl, &vork);
	nachk = zahl - vork;

        if (komma)
	   nk = (long)((double)(nachk * pow (10.0, (double)komma)));

	nk1 = (long)((double)(nachk * pow (10.0, (double)komma+1.0)));
	splitter = nk1 - (nk * 10L);

	if (splitter >= 5L)
	   nk++;

	if (komma == 0)
	{
	   if (splitter >= 5)
	      return vork+1.0;

	   return vork;
	}

	nachk = (double)nk / pow (10.0, (double)komma);
	vork += nachk;
	return vork;
}

BOOL TRech::test_abschl (int am)
{
BOOL t1,t2,t3,t4,t5,t6;

	t1 = (TpPars->abschlry == 1 || TpPars->abschlry == 41);
	t2 = ((TpPars->abschlry == 3 || TpPars->abschlry == 43) && (am == 3 || am == 6 || am == 9 || am == 12));
	t3 = ((TpPars->abschlry == 6 || TpPars->abschlry == 46) && (am == 6 || am == 12));
	t4 = ((TpPars->abschlry == 12 || TpPars->abschlry == 52) && am == 12);
	t5 = (TpPars->abschlry == 47 && (am == 3 || am == 9));
	t6 = (TpPars->abschlry == 48 && (am == 2 || am == 8));

	if (t1 || t2 || t3 || t4 || t5 || t6)
	   return TRUE;

	return FALSE;
}

long TRech::tageber (long date)
{
int tt_par, mm_par, jj_par;

	date_int (&tt_par, &mm_par, &jj_par, date);

	if (TpPars->tageb == 1 || TpPars->tageb == 4 || TpPars->tageb == 6)
	{
	   if (TpPars->abschlry > 40 || TpPars->ultimo)
	      if (tt_par >= 28 && mm_par == 2)
		 tt_par = 30;

	   if (tt_par > 30)
	      tg_par = (long)jj_par * 360L + (long)mm_par * 30L;
	   else
	      tg_par = (long)jj_par * 360L + ((long)mm_par - 1L) * 30L + (long)tt_par;
	}
	else
	   tg_par = DateToDay (date);

	return tg_par;
}

void TRech::vorrech ()
{
long tg;

	dat_par = ab_dat[a_ind];
	tg_par = tageber (dat_par);
	tg = tg_par - ab_tag;
	ab_tag = tg_par;

	if (verzinsung != 1)
	{
	   zi_kap = kap * (double)tg * TpPars->zssoll / divisor;
	   zi_rat = rat * (double)tg * TpPars->zssoll / divisor;
	}
	else
	{
	   zi_kap = kap * (double)tg * TpPars->zssoll / (divisor - (double)tg * TpPars->zssoll);
	   zi_rat = rat * (double)tg * TpPars->zssoll / (divisor - (double)tg * TpPars->zssoll);
	}
}

/* Einschränkung */

void TRech::einschr ()
{
long tg;

	rat = rat + (double)rat_anz[r_ind];

	if (TpPars->valuta == 0)
	{
	   dat_par = rat_dat[r_ind];
	   tg_par = tageber (dat_par);
	   tg = ab_tag - tg_par;

	   if (verzinsung == 1)
	      zi_rat = zi_rat + (double)rat_anz[r_ind] * (double)tg *
		       TpPars->zssoll / (divisor - (double)tg *
		       TpPars->zssoll);
	   else
	      zi_rat = zi_rat + (double)rat_anz[r_ind] * (double)tg *
		       TpPars->zssoll / divisor;
	}

	r_ind++;
}

/* Abschlußberechnung */

void TRech::abschlus ()
{
	switch (reh)
	{
	   case 0: kap += zi_kap;
		   rat += zi_rat;
	   break;

	   case 2: kap += (zi_kap + TpPars->spesen);
		   rat += zi_rat;
	   break;
	}

	a_ind++;
}

// Erstellen eines Ratenplans

double TRech::GetRate (double rahmen, long ragab, long dvon)
{
double ergrate;

	ab_tag = 0L;
	zi_rat = 0.0;
	zi_kap = 0.0;
	dat_par = 0L;

	if (rat_dat[r_ind] < dvon)
	   while (rat_dat[r_ind] < dvon && r_ind < max_rat)
	      r_ind++;

	dat_par = ragab;
	tageber (dat_par);
	kap = rahmen + TpPars->kosten;
	rat = 0.0;
	ab_tag = tg_par;
	vorrech ();

	while (r_ind < max_rat && a_ind < max_abs)
	{
	   if (rat_dat[r_ind] > ab_dat[a_ind])
	   {
	      abschlus ();
	      vorrech ();
	   }
	   else if (rat_dat[r_ind] < ab_dat[a_ind])
	      einschr ();
	   else if (verzinsung == 1 || verzinsung == 2)
	   {
	      abschlus ();
	      vorrech ();
	      einschr ();
	   }
	   else
	   {
	      einschr ();
	      abschlus ();
	      vorrech ();
	   }
	}

	if (verzinsung == 1 || verzinsung == 2)
	{
	   abschlus ();
	   einschr ();
	}
	else
	{
	   einschr ();
	   abschlus ();
	}

	if (rat != 0.0)
        {
           rat = (kap - TpPars->kapital) / rat;
	   ergrate = runden (rat, rund_fakt);

	   if (ergrate != rat && rund_fakt > 0)
              rat = ergrate + (1.0 / pow (10.0, (double)rund_fakt));
	   else if (rund_fakt == 0 && ergrate != rat)
	      rat = ergrate + 1.0;
	}

        return rat;
}

/************************************************************************
   Erstellung eines Tilgungsplans.

   Dieser wird in eine Datei ausgegeben. Die Datei besteht aus einem
   Kopf (Übergabestruktur) und einzelnen Datensätzen.
*************************************************************************/

// #$10100
int TRech::Ratenplan ()
{
	if (verzinsung == 0 || verzinsung == 2)
	{
	   if (TpPars->effekt)
	   {
	   int i = 0;
	   int ret;

	      TpPars->effformel = TpPars->zssoll;

	      while (i < 10000 && (ret = DekursivPlan ()) == -2)
	      {
		 TpPars->zssoll = TpPars->effformel;
		 i++;
	      }

	      if (ret != -2)
		 return ret;
fprintf (stderr, "bzins: %.2f, ezins: %.2f\n", TpPars->gewicht, TpPars->ezins);
	      return 0;
	   }

	   return DekursivPlan ();
	}

	return AntizipativPlan ();
}

// #$10110
int TRech::DekursivPlan ()
{
QString hdir = QDir::homeDirPath ();
QFile tmpFile, zaf;
int fd, index, i;
int real_rat, Abzug;
long tg, effend;
double zins, tilg, zi1, zi2, kzi;
long offset;
BOOL stop;
#ifdef _ZINSAENDERUNG
   int fdZins;
   long zoff, LastAend;
   ZIAEND Zi;
   double aZins;
   struct stat sbuf;
#endif

	/* Planerstellung */
	hdir.append("/.date_tbl.dat");
	tmpFile.setName(hdir);

	if (!TpPars->effekt)
	{
	   if (tmpFile.open(IO_ReadWrite | IO_Truncate) == FALSE)
	   {
	      KMessageBox::error(0, QString("Could not open file for reading: %1").arg(tmpFile.errorString()));
	      return 1;
	   }
	}
	else
	{
	   if (tmpFile.open(IO_ReadOnly) == FALSE)
	   {
	      KMessageBox::error(0, QString("Could not open file for reading: %1").arg(tmpFile.errorString()));
	      return 1;
	   }
	}

	fd = tmpFile.handle();
#ifdef _ZINSAENDERUNG
	// Wenn eine Zinssatzänderung gewünscht wurde, muß die Änderungs-
	// datei geöffnet werden.

	zoff = 0L;
        LastAend = 0L;		// Beinhaltet Datum der letzten Zinssatzänderung
	aZins = 0.0;
	memset (&Zi, 0, sizeof(ZIAEND));

	if (TpPars->ziaend)
        {
           hdir = QDir::homeDirPath ();
           hdir.append("/.zinsaend.dat");
           zaf.setName(hdir);
           fdZins = -1;

           if (zaf.open(IO_ReadOnly) == FALSE)
	      TpPars->ziaend = FALSE;
	   else
           {
	      fdZins = zaf.handle();
	      fstat (fdZins, &sbuf);

	      if (sbuf.st_size == 0L)
		 TpPars->ziaend = FALSE;
	      else
              {
		 read (fdZins, &Zi, sizeof(ZIAEND));
                 zoff += (long)sizeof(ZIAEND);
              }
	   }

	   if (!TpPars->ziaend && fdZins != -1)
              zaf.close ();
	}
#endif

	offset = 0L;
	index = max_abs + max_rat;

	/* Ausgangsdaten schreiben */
	if (!TpPars->effekt)
	{
	   write (fd, TpPars, sizeof (TPPARS));
	   offset += (long)sizeof (TPPARS);
	}

	/* Initialisierung der Schleife */

	a_ind = r_ind = 0;
	kap = TpPars->rahmen;
	zins = 0.0;
	TpPars->gesamt = kap;
	tilg = kzi = 0.0;
	tg = 0;
	TpPars->abschl = ab_dat[0];
	stop = FALSE;			// TRUE wenn Laufzeitende bei Ratenvorgabe
	real_rat = max_rat;
        Abzug = 0;			// wird nur bei Ratenvorgabe verwendet

	if (TpPars->effekt)
	   effend = TpPars->dvon + 10000L;	// 1 Jahr für Effektivzinsberechnung
	else
	   effend = 0L;

	/* Spesen dürfen nur einmal bei der Auszahlung auf das Kapital
	 * aufgeschlagen werden.
	 */
	if (!TpPars->effekt)
	{
	   DTable.datum = TpPars->ragab;
	   DTable.kz = 'U';		// Auszahlung
	   DTable.kapital = kap;
	   DTable.tilg = 0.0;
	   DTable.rate = 0.0;
	   DTable.zinsen = TpPars->kosten;
	   DTable.rkapi = kap + TpPars->kosten;
	   kap += TpPars->kosten;

	   write (fd, &DTable, sizeof (DTABLE));
	   offset += (long)sizeof (DTABLE);
	}

	/* Schleife zur Berechnung der Gesamtbelastung (Dekursiv) */

	for (i = 0; i < index; i++)
	{
#ifdef _ZINSAENDERUNG
	   // Ist eine Zinssatzänderung gewünscht?

	   if ((Zi.Datum < rat_dat[r_ind-1] || Zi.Datum < ab_dat[a_ind]) &&
	       zoff <= sbuf.st_size && TpPars->ziaend)
	   {
	      DTable.datum = Zi.Datum;
	      DTable.kz = 'Z';
	      DTable.kapital = kap;
	      index++;

	      if (a_ind > 0)
	      {
		 if (ab_dat[a_ind-1] < Zi.Datum)
		    ldat = ab_dat[a_ind-1];
		 else
		    ldat = Zi.Datum;

		 tg = tageber (Zi.Datum) - tageber (ldat);
	      }
	      else
	         tg = tageber (Zi.Datum) - tageber (TpPars->ragab);

	      aZins = kap * (double)tg * TpPars->zssoll / divisor;
	      kap += runden (aZins, rund_fakt);
              LastAend = Zi.Datum;
	      DTable.rate = Zi.Zins;
	      DekZiAend (fdZins, &zoff, sbuf.st_size, &Zi);
	      kap = DTable.kapital;
	   }
	   else if ((rat_dat[r_ind] <= ab_dat[a_ind] && r_ind < max_rat) || a_ind >= max_abs)
#else
	   if ((rat_dat[r_ind] <= ab_dat[a_ind] && r_ind < max_rat) || a_ind >= max_abs)
#endif
	   {
	      DTable.datum = rat_dat[r_ind];
	      DTable.kz = 'R';
	      DTable.kapital = runden (kap, rund_fakt);

	      if (r_ind > 0)
	      {
		 if (ab_dat[a_ind-1] > rat_dat[r_ind-1])
		    ldat = ab_dat[a_ind-1];
		 else
		    ldat = rat_dat[r_ind-1];
#ifdef _ZINSAENDERUNG
		 if (LastAend && LastAend > ldat)
		    ldat = LastAend;
#endif
		 tg = tageber (rat_dat[r_ind]) - tageber (ldat);
	      }
	      else
	         tg = tageber (rat_dat[r_ind]) - tageber (TpPars->ragab);

	      zi1 = kap * (double)tg * TpPars->zssoll / divisor;
#ifdef _ZINSAENDERUNG
	      if (LastAend)
	      {
		 LastAend = 0L;
		 zi1 += aZins;
	      }
#endif
              zi1 = runden (zi1, rund_fakt);
	      zins += zi1;
	      kzi += zi1;

	      if (TpPars->fixrate == TRUE)	/* Ratenvorgabe */
	      {
	         if (!stop && r_ind > 0 && DTable.rkapi < rat)
	         {
	            max_rat = r_ind + 1;
	            max_abs = a_ind + 1;
	            real_rat = max_rat - Abzug;
	            ab_dat[a_ind] = rat_dat[r_ind];
	            index = max_rat + max_abs;
	            stop = TRUE;
	         }
	      }

	      if (r_ind == (max_rat - 1)) 		/* letzte Rate */
	      {
		 if (reh != 1)
		 {
		    zi2 = (kap < rat) ? rat - kap : kap - rat;
		    zi2 = rat - zi2 + zins;
//	            zi2 = rat + ((TpPars->gesamt + zins) - (rat * (LFLOAT)real_rat));
		 }
	         else
	            zi2 = rat - ((rat * (double)real_rat) - TpPars->rahmen);

	         rat = zi2 + TpPars->spesen;
	      }

	      TpPars->lrate = rat;
	      tilg += rat;				/* Tilgung */

	      if (DTable.datum >= TpPars->dvon)		/* Restkapital */
	         kap -= rat;

	      DTable.rkapi = (kap >= 0.0) ? kap : 0.0;
	      DTable.tilg = 0.0;
	      DTable.rate = rat;
	      DTable.zinsen = zi1;
	      r_ind++;
	   }
	   else
	   {
	      DTable.datum = ab_dat[a_ind];
	      DTable.kz = 'A';

	      if (r_ind > 0 && rat_dat[r_ind-1] <= ab_dat[0])
	         DTable.kapital = TpPars->rahmen;
	      else
	         DTable.kapital = (kap >= 0.0) ? kap : 0.0;

	      kap += TpPars->spesen;
	      DTable.rate = 0.0;

	      if (r_ind > 0)
              {
	         if (ab_dat[a_ind-1] > rat_dat[r_ind-1])
	            ldat = ab_dat[a_ind-1];
	         else
	            ldat = rat_dat[r_ind-1];
#ifdef _ZINSAENDERUNG
		 if (LastAend && LastAend > ldat)
		    LastAend = 0L;
#endif
		 tg = tageber (ab_dat[a_ind]) - tageber (ldat);

	         if (tg > 0)
                 {
		    zi1 = kap * (double)tg * TpPars->zssoll / divisor;
#ifdef _ZINSAENDERUNG
	            if (LastAend)
	            { 
		       LastAend = 0L;
		       zi1 += aZins;
	            }
#endif
		    zins += zi1;
	            kzi += runden (zi1, rund_fakt);
	            zins = runden (zins, rund_fakt);
		 }
#ifdef _ZINSAENDERUNG
		 else if (LastAend)
		    LastAend = 0L;
#endif
	      }

	      DTable.zinsen = zins;
	      TpPars->gesamt += zins + TpPars->spesen;	/* Gesamtbelastung */

	      if (reh != 2)
	         tilg -= zins;      		/* Tilgung - Zinsen */

	      if (DTable.datum < TpPars->dvon)
	         DTable.tilg = 0.0;
	      else
	         DTable.tilg = tilg;

	      if (reh != 1)
	         kap += zins;

	      DTable.rkapi = (kap >= 0.0) ? kap : 0.0;
	      zins = 0.0;
	      tilg = 0.0;
	      a_ind++;
	   } /* end if */

	   if (DTable.datum < TpPars->dvon && DTable.kz == 'R')
	   {
              if (TpPars->fixrate)
	         Abzug++;
	      else
	         real_rat--;

	      continue;
	   }

	   if (!TpPars->effekt)
	   {
	      write (fd, &DTable, sizeof (DTABLE));
	      offset += (long)sizeof (DTABLE);
	   }
	   else if (DTable.datum >= effend)
	      break;
	} /* end for */

	if (TpPars->fixrate == TRUE)
	   TpPars->dbis = rat_dat[r_ind-1];

	TpPars->anzraten = real_rat;
	DTable.datum = (long)real_rat;		/* Laufzeit */
	DTable.kz = 'E';			/* Ergebnis */
	DTable.kapital = TpPars->rahmen;
	DTable.tilg = TpPars->gesamt;
	DTable.rate = 0.0;
	TpPars->ezins = TpPars->gesamt - TpPars->rahmen;

	if (TpPars->zuschprz > 0.0)
	   TpPars->zuschuss = runden (TpPars->ezins / 100 * TpPars->zuschprz, rund_fakt);
	else
	   TpPars->zuschuss = 0.0;

	DTable.zinsen = TpPars->gesamt - TpPars->rahmen;
	TpPars->gesamt -= TpPars->zuschuss;

	// Annuitätenzuschuß berechnen und anzeigen

	if (TpPars->zuschannu > 0.0 && TpPars->gesamt > 0.0)
	{
	   TpPars->anzuschuss = TpPars->ergrate / 100.0 * TpPars->zuschannu;
	   TpPars->antotal = TpPars->anzuschuss * ((double)real_rat - 1.0) + (TpPars->lrate / 100.0 * TpPars->zuschannu);
	   TpPars->antotal -= TpPars->zuschuss;
	}
	else
	   TpPars->anzuschuss = TpPars->antotal = 0.0;

	DTable.rkapi = TpPars->lrate;

	if (!TpPars->effekt)
	   write (fd, &DTable, sizeof (DTABLE));
#ifdef _ZINSAENDERUNG
//	if (TpPars->gewicht > 0.0)
//	   TpPars->zssoll = TpPars->gewicht;

	zaf.close();
#endif
	tmpFile.flush();

	if (!TpPars->effekt)
	{
	   lseek (fd, 0L, 0);
	   write (fd, TpPars, sizeof (TPPARS));
	}
	else
	{
	   // Zinsen nach einem Jahr ermitteln
	   tmpFile.flush();
	   lseek (fd, (long)sizeof(TPPARS), 0);
	   zins = 0.0;

	   while (read (fd, &DTable, sizeof(DTABLE)) >= sizeof(DTABLE))
	   {
	      if (DTable.kz == 'R' && DTable.datum >= effend)
		 break;

	      if (DTable.kz == 'R')
		 zins += DTable.zinsen;
	   }

	   if ((TpPars->ezins - 0.1) < zins && (TpPars->ezins + 0.1) > zins)
	   {
	      tmpFile.close();
	      TpPars->gewicht = zins;
	      return 0;
	   }
	   else
	   {
	      tmpFile.close();
	      TpPars->gewicht = zins;

	      if (TpPars->ezins < zins)
		 TpPars->effformel += 0.0001;
	      else
		 TpPars->effformel -= 0.0001;

	      return -2;		// Für nächste Iteration präparieren.
	   }
	}

	tmpFile.close ();
	return 0;
}

#ifdef _ZINSAENDERUNG
void TRech::DekZiAend (int fdZins, long *zoff, long size, ZIAEND *Zi)
{
int old_rind, old_aind;
long datum;
double old_kap;

	TpPars->gewicht = TpPars->zssoll;
	TpPars->zssoll = Zi->Zins;

	if (Zi->Rate)
        {
	   old_kap = kap;
	   old_rind = r_ind;
	   old_aind = a_ind;

	   if (rat_dat[r_ind] > ab_dat[a_ind])
	      datum = ab_dat[a_ind];
	   else
	      datum = rat_dat[r_ind];

	   GetRate (kap, Zi->Datum, datum);
	   kap = old_kap;
	   r_ind = old_rind;
	   a_ind = old_aind;
	   TpPars->ergrate = rat;
	}
	else if (Zi->FixRate)
        {
	   rat = Zi->NewRate;
	   TpPars->ergrate = rat;
	}

	if (*zoff < size)
	   read (fdZins, Zi, sizeof(ZIAEND));
	else
	   close (fdZins);

        *zoff += (long)sizeof(ZIAEND);
}

#endif
int TRech::AntizipativPlan ()
{
QString hdir = QDir::homeDirPath ();
QFile tmpFile;
int fd, index, i;
int real_rat, Abzug;
long t1, t2, r_dat, old_par, r_tg, a_tg;
double zins, tilg, kzi, sumrat;
long offset, loff;
BOOL stop;
DTABLE old_tab;

	/* Planerstellung */
	hdir.append("/.date_tbl.dat");
	tmpFile.setName(hdir);

	if (tmpFile.open(IO_ReadWrite | IO_Truncate) == FALSE)
	{
	   KMessageBox::error(0, QString("Could not open file for reading: %1").arg(tmpFile.errorString()));
	   return 1;
	}
	

	fd = tmpFile.handle();
	offset = 0L;
	index = max_abs - 1 + max_rat;

	/* Ausgangsdaten schreiben */
	write (fd, TpPars, sizeof (TPPARS));
	offset += (long)sizeof (TPPARS);

	/* Initialisierung der Schleife */

	a_ind = r_ind = 0;
	kap = TpPars->rahmen;
	zins = 0.0;
	TpPars->gesamt = kap;
	tilg = kzi = 0.0;
	TpPars->abschl = ab_dat[0];
	stop = FALSE;			// TRUE wenn Laufzeitende bei Ratenvorgabe
	real_rat = max_rat;
        Abzug = 0;			// wird nur bei Ratenvorgabe verwendet

	/* Schleife zur Berechnung der Gesamtbelastung (Antizipativ) */
	
	a_ind++;			/* Start bei 1! */
	ab_tag = tageber (ab_dat[a_ind]);
	tageber (TpPars->ragab);
	tg_alt = tg_par;
	sumrat = 0.0;
	DTable.rkapi = runden (kap, rund_fakt);
	DTable.kapital = runden (kap, rund_fakt);
	loff = offset;
	old_tab.datum = ab_dat[0];
	old_tab.kz = 'A';
	old_tab.kapital = TpPars->rahmen;
	write (fd, &old_tab, sizeof (DTABLE));	/* Platzhalter */
	offset += (long)sizeof (DTABLE);
	r_dat = 0L;

	for (i = 0; i < index-1; i++)
	{
	   if ((rat_dat[r_ind] < ab_dat[a_ind] && r_ind < max_rat) || a_ind >= max_abs)
	   {
	      DTable.datum = rat_dat[r_ind];
	      DTable.kz = 'R';

	      tageber (rat_dat[r_ind+1]);
	      t1 = ab_tag - tg_alt;
	      t2 = ab_tag - tg_par;

	      if (t2 < 0L)
		 t2 = 0L;

              // Berechnung der letzten Rate
	      if (rat > (DTable.rkapi - TpPars->kapital))
	         rat = runden (DTable.rkapi - TpPars->kapital, rund_fakt);

	      sumrat += rat;

//              if (reh == 1)		// Kapitalraten
	         kap -= rat;

	      if (reh != 1)		// Pauschalraten
	      {
	         kzi = kap * TpPars->zssoll * ((double)t1 *
	               (divisor - (double)t2 * TpPars->zssoll) -
		       (double)t2 * (divisor - (double)t1 * TpPars->zssoll)) /
		       ((divisor - (double)t1 * TpPars->zssoll) *
		       (divisor - (double)t2 * TpPars->zssoll));
	      }
	      else			// Kapitalraten
//	         kzi = kap * (tg_par - tg_alt) * TpPars->zssoll / divisor;
		 kzi = kap * (t1 - t2) * TpPars->zssoll / divisor;

	      kzi = runden (kzi, rund_fakt);
	      tg_alt = tg_par;
	      zins += kzi;

              if (reh == 1)		// Kapitalraten
		 DTable.rkapi = DTable.kapital - sumrat;
	      else			// Pauschalraten
		 DTable.rkapi = DTable.kapital + zins - sumrat;

	      if (TpPars->fixrate == TRUE)	/* Ratenvorgabe */
	      {
		 if (!stop && r_ind > 0 && DTable.rkapi < rat)
	         {
	            max_rat = r_ind + 1;
	            max_abs = a_ind + 1;
	            ab_dat[a_ind] = rat_dat[r_ind];
                    real_rat = max_rat - Abzug;
	            index = max_rat + max_abs;
	            stop = TRUE;
	         }
	      }

              if (reh == 1)		// Kapitalraten
		 DTable.tilg = rat;
	      else                 	// Pauschalraten
		 DTable.tilg = rat - kzi;

	      tilg += DTable.tilg;
	      TpPars->lrate = rat;

	      DTable.rate = rat;
	      DTable.zinsen = kzi;
	      r_ind++;
	   }
	   else			/* Abschluß */
	   {
	      DTable.datum = ab_dat[a_ind];

	      if (i == (index-2))
	      {
		 DTable.kz = 'R';
		 max_rat++;
//		 TpPars->lrate = DTable.kapital - tilg;
	      }
	      else
	         DTable.kz = 'A';

	      if (a_ind > 1)
              {
                 old_par = tg_par; 

		 if (reh == 1)			// Kapitalraten
                 {
		    r_tg = tageber (r_dat);
                    a_tg = tageber (ab_dat[a_ind-1]);
		    t1 = r_tg - a_tg;
		    t2 = 0L;
		 }
		 else
		 {
		    a_tg = tageber (ab_dat[a_ind]);
		    tageber (ab_dat[a_ind-1]);
		    t1 = a_tg - tg_par;
		    tageber (r_dat);
		    t2 = ab_tag - tg_par;
		 }

		 tg_par = old_par;

		 if (reh != 1)			// Pauschalraten
                 {
		    kzi = DTable.kapital * TpPars->zssoll * ((double)t1 *
	                  (divisor - (double)t2 * TpPars->zssoll) -
		          (double)t2 * (divisor - (double)t1 * TpPars->zssoll)) /
		          ((divisor - (double)t1 * TpPars->zssoll) *
			  (divisor - (double)t2 * TpPars->zssoll));
                 }
		 else                           // Kapitalraten
		    kzi = DTable.kapital * t1 * TpPars->zssoll / divisor;

		 kzi = runden (kzi, rund_fakt);
		 zins += kzi;

		 if (reh != 1)
		 {
                    tilg -= kzi;
		    DTable.rkapi = DTable.kapital - tilg;
                 }
	      }

	      DTable.kapital -= tilg;
	      r_dat = rat_dat[r_ind];

	      if (i == (index - 2))
	      {
	         DTable.rate = DTable.kapital;
		 TpPars->lrate = DTable.rate;
	         DTable.zinsen = 0.0;
	         DTable.tilg = DTable.kapital;
	         DTable.rkapi = 0.0;
	      }
	      else
	      {
	         DTable.rate = runden (sumrat, rund_fakt);
	         DTable.zinsen = zins;
	         DTable.tilg = tilg;
	      }

	      TpPars->gesamt += zins;		/* Gesamtbelastung */

	      tmpFile.flush();
	      lseek (fd, loff, 0);
	      /* Füllen der Struktur */
	      old_tab.tilg = tilg;
	      old_tab.rate = 0.0;
	      old_tab.zinsen = zins;

              if (reh == 1)
		 old_tab.rkapi = old_tab.kapital;
              else
		 old_tab.rkapi = old_tab.kapital + zins;

	      write (fd, &old_tab, sizeof (DTABLE));
	      old_tab.kapital = DTable.kapital;
	      old_tab.datum = DTable.datum;
	      lseek (fd, offset, 0);
	      loff = offset;

//              if (reh == 1)			// Kapitalraten
		 kap = DTable.kapital;

	      zins = 0.0;
	      tilg = 0.0;
	      sumrat = 0.0;
	      a_ind++;
	      ab_tag = tageber (ab_dat[a_ind]);
	   } /* end if */

	   if (DTable.datum <= ab_dat[0] && DTable.datum < TpPars->dvon &&
	       DTable.kz == 'R')
	   {
	      if (TpPars->fixrate)
		 Abzug++;
	      else
	         real_rat--;

	      continue;
           }

	   write (fd, &DTable, sizeof (DTABLE));
	   offset += (long)sizeof (DTABLE);
	} /* end for */

	if (TpPars->fixrate == TRUE)
	   TpPars->dbis = rat_dat[r_ind-1];

	TpPars->anzraten = real_rat;
	DTable.datum = (long)real_rat;		/* Laufzeit */
	DTable.kz = 'E';			/* Ergebnis */
	DTable.kapital = TpPars->rahmen;
	DTable.tilg = TpPars->gesamt;
	DTable.rate = 0.0;
	TpPars->ezins = TpPars->gesamt - TpPars->rahmen;

	if (TpPars->zuschprz > 0.0)
	   TpPars->zuschuss = runden (TpPars->ezins / 100 * TpPars->zuschprz, rund_fakt);
	else
	   TpPars->zuschuss = 0.0;

	DTable.zinsen = kzi;
	TpPars->gesamt -= TpPars->zuschuss;

	// Annuitätenzuschuß berechnen und anzeigen

	if (TpPars->zuschannu > 0.0 && TpPars->gesamt > 0.0)
	{
	   TpPars->anzuschuss = TpPars->ergrate / 100.0 * TpPars->zuschannu;
	   TpPars->antotal = TpPars->anzuschuss * ((double)real_rat - 1.0) + (TpPars->lrate / 100.0 * TpPars->zuschannu);
	   TpPars->antotal -= TpPars->zuschuss;
	}
	else
	   TpPars->anzuschuss = TpPars->antotal = 0.0;

	DTable.rkapi = TpPars->lrate;
	write (fd, &DTable, sizeof (DTABLE));
	tmpFile.flush();
	lseek (fd, 0L, 0);
	write (fd, TpPars, sizeof (TPPARS));
	tmpFile.close ();
	return 0;
}

void TRech::init_global_vars ()
{
int i;

	ab_tag = 0L;
	zi_rat = 0.0;
	zi_kap = 0.0;
	dat_par = 0L;
	reh = 0;
	divisor = 0.0;
	a_ind = 0;
	r_ind = 0;
	max_abs = max_rat = 0;
	pos = 0L;
	a_dat = 0L;
	tg_par = tg_alt = 0L;
	r_dat = 0L;
	ldat = 0L;
	rat = kap = 0.0;

	for (i = 0; i < 1200; i++)
	{
	   rat_dat[i] = 0L;
	   ab_dat[i] = 0L;
	   rat_anz[i] = 0L;
	}
}
